package com.etl.es.service;

import com.etl.es.document.ChannelDocument;
import com.etl.es.repository.ChannelRepository;
import com.google.common.collect.Maps;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import java.util.Map;
import java.util.Objects;

/**
 * ES渠道服务
 *
 * @author: chenfenghai
 * @version: 1.0
 * @date: 2020-10-29 14:51
 */
@Slf4j
@Service
public class ChannelService {

    @Autowired
    ChannelRepository channelRepository;

    /**
     * 缓存渠道MAP键值对
     */
    private final Map<String, ChannelDocument> channelMap = Maps.newConcurrentMap();

    /**
     * 初始化缓存渠道MAP键值对
     */
    @PostConstruct
    private void initChannelMap() {
        channelRepository.findAll().forEach(
                channelDocument -> channelMap.put(channelDocument.getChannelCode(), channelDocument));
    }

    /**
     * 保存或替换渠道文档
     *
     * @param channelUid 渠道UID
     * @param channel    初始渠道文档
     * @return ChannelDocument
     */
    public ChannelDocument saveOrReplaceChannelDocument(String channelUid, ChannelDocument channel) {
        // 渠道UID的长度为1时，表示是系统定义的本地渠道，直接设置渠道UID为渠道编码
        if (StringUtils.length(channelUid) == 1) {
            channel.setChannelCode(channelUid);
        }
        // 如果缓存中存在该渠道，则直接获取并返回
        ChannelDocument newChannel;
        if (StringUtils.isNotEmpty(channel.getChannelCode())
                && (newChannel = channelMap.get(channel.getChannelCode())) != null) {
            return newChannel;
        }
        // 保存渠道文档，并存放到缓存中
        return saveChannelDocument(channel);
    }

    /**
     * 保存渠道文档，并存放到缓存中
     *
     * @param channel 初始渠道文档
     * @return ChannelDocument
     */
    private synchronized ChannelDocument saveChannelDocument(ChannelDocument channel) {
        // 异常数据处理，如果渠道编码为空，则直接默认为未知渠道
        if (StringUtils.isEmpty(channel.getChannelCode())) {
            channel.setChannelCode("11");
            channel.setChannelName("未知");
        }
        // Double Check
        // 如果缓存中存在该渠道，则直接获取并返回
        ChannelDocument newChannel = channelMap.get(channel.getChannelCode());
        if (Objects.nonNull(newChannel)) {
            return newChannel;
        }
        // 设置渠道类型名称
        if (channel.getChannelTypeCode().intValue() == 0) {
            channel.setChannelTypeName("本地");
        } else {
            channel.setChannelTypeName("网售");
        }
        // 保存到ES
        channelRepository.save(channel);
        // 保存到缓存
        channelMap.putIfAbsent(channel.getChannelCode(), channel);
        return channel;
    }
}
